;	KD11 CONSOLE FUNCTIONS PROGRAM
;	BY JEFF SCOTT

;	KA11 VERSION OF THE KD11 ODT  PACKAGE
;	THE ONLY REAL PROBLEM IS THAT HALTS
;	TO NOT FORCE ENTRYS TO THE PACKAGE
;	ALL OTHER FUNCTIONS ARE SIMULATED IN THE PACKAGE
;	THAT STARTS AT LOCATION 1000 IN THIS LISTING
;	FOR THAT PACKAGE THE SWITCH REGISTER BIT 0
;	IS THE RESET BUTTON AND START BUTTON IS BIT 1


R0	=	%0		;GENERAL REGISTER 0
R1	=	%1		;GENERAL REGISTER 1
R2	=	%2		;GENERAL REGISTER 2
R3	=	%3		;GENERAL REGISTER 3
R4	=	%4		;GENERAL REGISTER 4
R5	=	%5		;GENERAL REGISTER 5
SP	=	%6		;PROCESSOR STACK REGISTER
PC	=	%7		;PROGRAM COUNTER (MOD 2^16)

STATUS	=	177776		;STATUS REGISTER
PR7	=	340		;PROCESSOR PRIORITY 7 MASK

KBD0	=	177560		;KEYBOARD (TTY,LA30,VT05, OR VT06)
TTY0	=	177564		;PRINTER (TTY,LA30,VT05, OR VT06)

LOWASC	=	040		;LOWER PRINTABLE ASCII CHARACTER
HGHASC	=	137		;UPPER LIMIT ON ASCII
BELL	=	007		;ASCII VALUE OF <BELL>
LF	=	012		;ASCII VALUE OF <LF>
CR	=	015		;ASCII VALUE OF <CR>
ESC	=	033		;ASCII VALUE OF <ESC>
ALT1	=	175		;ASCII VALUE OF <ALT1>
ALT2	=	176		;ASCII VALUE OF <ALT2>

TBIT	=	020		;T-BIT POSITION IN STACKED STATUS
TVEC	=	14		;TRACE VECTOR LOCATION

RTT	=	RTI		;FOR THE KA11
NOP	=	240		;FOR THE KA11

.	=	10000		;JUST ORGIN SOMEPLACE IN 4K FOR NOW
	BR	RESET		;RESET BUTTON ENTRY POINT
	BR	STOP		;STOP BUTTON ENTRY POINT
TRTENT:	DEC	SINGLE		;DECREMENT SINGLE INSTR COUNT
	BNE	STRT01		;IF NOT EXAUSTED KEEP GOING
STOP:	MOV	(SP)+,USRPC	;GET STACKED PC
	MOV	(SP)+,USRST	;AND STATUS REGISTER
RESET:	MOV	SP,USRSP	;SAVE THIS STACK POINTER
	MOV	#USRSP,SP	;AND INSTITUTE OUR OWN
	MOV	#TRTENT,@#TVEC	;SET UP THE TRT VECTOR
	MOV	#PR7,@#TVEC+2	;START OFF AT PR7
	MOV	R5,-(SP)	
	MOV	R4,-(SP)
	MOV	R3,-(SP)	;SAVE THE USER REGISTERS
	MOV	R2,-(SP)
	MOV	R1,-(SP)
	MOV	R0,-(SP)
	MOVB	ODTPRI,R0	;GET PRIORITY BYTE
	BPL	LOAD00		;IF MINUS USE HIS PRIORITY
	MOV	USRST,R0	;GET HIS PRIORITY
	BIC	#TBIT,R0	;FOR THE KA11 AGAIN
	BR	LOAD01		;AND GO PUT IT WHERE IT BELONGS
LOAD00:	ROR	R0
	ROR	R0		;SHIFT LOW 3 BITS TO HIGH 3 BITS
	ROR	R0
	ROR	R0
LOAD01:	MOVB	R0,@#STATUS	;RAISE-LOWER PRIORITY
LOAD02:	MOV	#MSG2,R0	;SET UP <CR> <LF> <=>
	JMP	SCAN08		;BRANCH TO A PRINT CALL

ONCE:	TST	R1		;SEE IF ANYTHING TYPED
	BNE	ONCE00		;IF # TYPED HONOR IT
	INC	R1		;ELSE MAKE 1 TIME
ONCE00:	MOV	R1,SINGLE	;SAVE THE COUNT
	BIS	#TBIT,USRST	;SET THE TBIT FOR AS TO GET HIM BACK
	BR	STRT00		;AND START HIM UP

STRTHM:	TST	R0		;SEE IF HE WANTS START OR CONTINUE
	BEQ	STRT02		;IF NO NUMBERS THEN CONTINUE
	MOV	R1,USRPC	;STORE NEW PC
STRT02:	BIC	#TBIT,USRST	;CLEAR ANY LEFT OVER T BITS
STRT00:	MOV	(SP)+,R0
	MOV	(SP)+,R1
	MOV	(SP)+,R2
	MOV	(SP)+,R3	;RESTORE THE REGISTERS
	MOV	(SP)+,R4
	MOV	(SP)+,R5
	MOV	(SP)+,SP
	MOV	USRST,-(SP)	;SET UP FOR AN RTT
	MOV	USRPC,-(SP)	;SET THE NEW PC
	JSR	PC,CRLF		;FINISH UP THIS LINE
	MOVB	USRKSR,@#KBD0	;RESTORE KEYBOARD REGISTER
	MOVB	USRTSR,@#TTY0	;AND TELETYPE REGISTER ALSO
STRT01:	RTT
OPNWD:
OPNBYT:
	TSTB	R0		;SEE IF ANY NEW ADDRESS
	BNE	OPEN03		;BRANCH IF ADDRESS ALREADY IN R1
	MOV	ADDR,R1		;ELSE GET THE OLD STORED ONE
OPEN03:	MOV	R1,DOT		;SAVE THIS LOCATION FOR LATTER
OPEN00:	ADD	R4,PC		;DISPATCH--BYT IS 0 WD IS 2
	BR	OPEN02		;BRANCH FOR BYTE MODE
	BIT	R1,#1		;SEE IF AN EVEN ADDRESS
	BNE	OPEN24		;BRANCH IF REALLY A BYTE
	MOV	(R1),R0		;GET THE WORD
	JSR	PC,PRINTW	;PRINT OUT AS A WORD
OPEN01:	MOVB	R4,STYLE	;SAVE THE TYPE OF OPEN FOR <CR> TYPES
	MOV	R1,ADDR		;SAVE THE ADDRESS FOR NULL OPEN
	BR	SCANER		;AND RESUME THE SCAN

OPEN02:	MOVB	(R1),R2		;GET THE BYTE IN R2
	JSR	PC,ECHOIT	;TYPE IT IF PRINTABLE
	MOV	R2,R0		;PUT IN R0 FOR PRINTB
	JSR	PC,PRINTB	;GO PRINT IT
	BR	OPEN01		;AND STORE AND RESUME

OPNEXT:
EOL:
OPNLNK:
OPNPCI:
OPNIND:
OPNRET:
OPNBR:
	MOV	R1,R2		;SAVE THE TYPED NUMBER
	MOV	ADDR,R1		;GET THE ADDRESS OF INTEREST
	MOV	R4,R5		;SAVE THE TYPE
	MOVB	STYLE,R4	;GET THE TYPE OF OPEN
	BLT	OPEN11		;BRANCH IF CLOSED ALREADY
	COM	STYLE		;SET CLOSED IF NOTHING ELSE HAPPENS
	TSTB	R0		;SEE IF HE TYPED ANYTHING
	BEQ	OPEN12		;BRANCH IF NOTHING TO DO
	ADD	R4,PC		;SEE IF WORD OR BYTE MODIFY
	BR	OPEN10		;BRANCH IF A BYTE
	MOV	R2,(R1)		;STORE THE UPDATED VERSION
	BR	OPEN12		;AND GO SEPARATE WAYS
OPEN10:	MOVB	R2,(R1)		;STORE A BYTE THIS TIME
	BR	OPEN12		;AND NEXT DISPATCH
OPEN11:	COM	R4		;GET REAL VALUE BACK
OPEN12:	ADD	R5,PC		;AND AWAY WE GO
	NOP			;CAN'T GET HERE FROM THERE
	NOP			;DITTO
	BR	LOAD02		;<CR>  CLOSE
	BR	OPEN20		;<LF> OPEN NEXT
	BR	OPEN25		;L     OPEN ADDITIVE LINKED
	BR	OPEN30		;>    OPEN RELATIVE BRANCH
	BR	OPEN35		;@    OPEN INDIRECT
	BR	OPEN40		;_    OPEN INDEXED "PC"
				;<    OPEN RETRUN STYLE
	MOV	DOT,R1		;GET THE OLD VALUE OF ADDR
OPEN20:	MOV	R1,DOT		;STORE THE NEW VALUE OF DOT
OPEN21:	ADD	R4,PC		;DISPATCH ON TYPE OF OPEN
	DEC	R1		;-1+2=1 FOR BYTE MODE
	CMPB	(R1)+,(R1)+	;JUST PLAIN 2 FOR WORD MODE
OPEN22:	JSR	PC,CRLF		;START A NEW LINE NOW
	MOV	R1,R0		;FOR PRINTW'S BENIFIT
	JSR	PC,PRINTW	;PRINT OUT THE VALUE OF THE ADDR
	ADD	R4,PC		;DISPATCH AGAIN
	BR	OPEN24		;BRANCH IF A BYTE
	MOVB	#'/,R2		;SET UP THE OLE' /
OPEN23:	JSR	PC,PRINTC	;PRINT THE \ OR /
	BR	OPEN00		;AND NOW OPEN THE NEW LOCATION
OPEN24:	MOVB	#'\,R2		;GET A PROPER \
	CLR	R4		;FOR ODD TYPE WORDS
	BR	OPEN23		;AND IT'S OFF TO THE RACES
OPEN25:	JSR	PC,CHKWM	;CHECK FOR WORD MODE
	ADD	(R1),R1		;LINK DOWN THE LIST
	BR	OPEN45		;AND RESUME LIKE THE OTHERS
OPEN30:	MOVB	(R1),R2		;GET THE OFFSET
	ASL	R2		;MAKE A WORD INDEX
	ADD	R2,R1		;ADD THE OFFSET
	TST	(R1)+		;AND THE PC WOULD HAVE BEEN HERE
	BR	OPEN45		;AND RESUME LIKE ALL THEM

OPEN35:	JSR	PC,CHKWM	;CHECK FOR WORD MODE
	MOV	(R1),R1		;LIKE DEFERED MAN DEFERED
	BR	OPEN45		;RESUME THE SCAN NOW

OPEN40:	JSR	PC,CHKWM	;WORD MODE IS NECESSARY
	ADD	(R1)+,R1	;REAL INDEXED "PC" MODE
OPEN45:	BIT	R1,#1		;SEE IF TURNED ODD ON US
	BEQ	OPEN22		;IF EVEN NO CHANGE
	CLR	R4		;ELSE MUST BE BYTE MODE
	BR	OPEN22		;GO LIKE <LF>


CHKWM:	TST	R4		;SEE IF WORD MODE
	BNE	GET00		;RETURN IF 2 OR WORD MODE
	TST	(SP)+		;ELSE POP THE RETURN
	BR	SCAN04		;AND SHOW AN ERROR

SCANER:	CLR	R0		;CLEAR FLAGS WORD
SCAN09:	CLR	R1		;CLEAR # TO BE
SCAN00:	JSR	PC,GETONE	;GO GET A CHARACTER - RETURNED IN R2
	SUB	#'0,R2		;CONVERT TO BINARY IF 0-7
	BMI	SCAN02		;BRANCH IF DELIMETER
	CMP	R2,#007		;SEE IF A NUMBER
	BGT	SCAN02		;EXIT FROM NUMERICAL SCAN IF ILLEGAL
	ASL	R1
	ASL	R1		;MULTIPLY BY 8
	ASL	R1
	TST	R0		;SEE IF NEGATIVE NUMBER
	BPL	SCAN01		;BRANCH IF POSITIVE
	NEG	R2		;MAKE CURRENT DIGIT NEGATIVE
SCAN01:	ADD	R2,R1		;ADD IN THE CURRENT DIGIT
	INCB	R0		;SHOW AT LEAST ON DIGIT TYPED
	BR	SCAN00

SCAN02:	MOV	#CMDCHR,R3	;GET COMMAND CHARACTERS TABLE ADDRESS
	CLR	R4		;INDEX INTO BRANCH TABLE
SCAN03:	CMPB	R2,(R3)+	;SEE IF IT MATCHES
	BEQ	SCAN05		;IF SO GO DISPATCH
	TST	(R4)+		;POP THE INDEX WORD
	TSTB	(R3)		;SEE IF END OF TABLE REACHED
	BNE	SCAN03		;IF NOT NULL TRY AGAIN
SCAN04:	MOV	#MSG1,R0	;SET UP ? <CR> <LF> *
SCAN08:	JSR	PC,PRINTL	;PRINT IT OUT
	BR	SCANER		;AND START ALMOST ALL OVER

SCAN05:	MOV	CMDTBL(R4),PC	;GO TO THE ROUTINE

SPECAL:	MOVB	#'$,R2		;<ESC> DIDN'T PRINT SO SET UP $
	JSR	PC,PRINTC	;AND PRINT IT OUT
	JSR	PC,GETONE	;GET ANOTHER (THE NEXT) CHARACTER
	MOV	#SPCCHR,R1	;START OF SPECIAL NAMES
SPEC00:	CMPB	R2,(R1)+	;SEE IF IT MATCHES THE PROTOTYPE
	BEQ	SPEC02		;IF FOUND EXIT NOW
	TSTB	(R1)		;SEE IF THE END OF THE TABLE
	BNE	SPEC00		;IF MORE KEEP SCANNING
	BIC	#177770,R2	;CLEAR ALL BUT LOW ORDER 3 BITS
SPEC01:	ASL	R2		;MAKE A BYTE ADDRESS
	ADD	#USRR0,R2	;MAKE ABSOLUTE ADDRESS
	CLR	R1		;MAKE THE NUMBER SO FAR 0
	BR	SCAN01		;CONSIDER ADDITIVE

SPEC02:	SUB	#SPCCHR-20,R1	;COMPUTE INDEX FROM USRR0
	MOV	R1,R2		;PUT IT IN THE RIGHT REGISTER
	BR	SPEC01		;AND REJOIN SPECAL

MINUS:	MOV	#100000,R0	;SET-SWITCH
	BR	SCAN09		;CLEAR THE NUMBER THEN RESUME THE SCAN
CRLF:	MOV	#MSG3,R0	;ADDRESS OF THE <CR><LF> STRING
PRINTL:	MOVB	(R0)+,R2	;GET A CHARACTER
	BEQ	PRNT00		;IF NULL EXIT NOW
	MOV	#PRINTL,-(SP)	;SHOW A RETURN TO PRINTL
PRINTC:	TSTB	@#TTY0		;CHECK READY FLA
	BPL	PRINTC		;LOOP IF STILL PRINTING
	MOVB	R2,@#TTY0+2	;SHOVE IT OUT
PRNT00:	RTS	PC		;AND RETURN

GETONE:	TSTB	@#KBD0		;WAIT FOR YEA OLE DONE BIT
	BPL	GETONE		;LOOP TILL SOME ACTION
	MOVB	@#KBD0+2,R2	;GET THE CHARACTER
	BIC	#177600,R2	;CLEAR THE PARITY BIT + SIDE EFFECT
	BEQ	GETONE		;EXIT IF NULL
ECHOIT:	CMPB	R2,#LOWASC	;SEE IF IN VALID PRINTABLE RANGE
	BLT	GET00		;EXIT IF NOT PRINTABLE
	CMPB	R2,#HGHASC	;SEE IF JUST RIGHT
	BLT	PRINTC		;BRANCH IF PRINTABLE
GET00:	RTS	PC		;ELSE EXIT WITH NO MARK ON THE PAPER

PRINTB:	MOV	#020114,R2	;SET UP A BYTE CONTROL WORD
	SWAB	R0		;PUT IN HIGH ORDER END OF REGISTER
	BR	PRINTO		;AND PRINT OUT AS OCATL
PRINTW:	MOV	#002230,R2	;SET UP A WORD MASK
PRINTO:	ASL	R0		;GET A BIT FROM THE INPUT NUMBER
	ROLB	R2		;AND PUT IT IN THE CHARACTER
	BCC	PRINTO		;IF FLAG'S NOT OUT LOOP FOR MORE
	JSR	PC,PRINTC	;PRINT THE CHARACTER
	CLRB	R2		;RESET THE FLAG AND CHARACTER
	BISB	#023,R2		;SET END BIT AND ASCII START
	ASL	R2		;SEE IF ALL DIGITS ARE DONE
	BCC	PRINTO		;LOOP IF MORE TO DO
	MOVB	#' ,R2		;SET UP A TRAILING SPACE
	BR	PRINTC		;AND PRINT THEN RETURN

CMDCHR:	.BYTE	'\-'0		;OPEN BYTE
	.BYTE	'/-'0		;OPEN WORD
	.BYTE	CR-'0		;END OF LINE - MODIFY OPEN
	.BYTE	LF-'0		;OPEN NEXT
	.BYTE	'L-'0		;OPEN AS ADDITIVE LINKED LIST
	.BYTE	'>-'0		;OPEN AS BRANCH
	.BYTE	'@-'0		;OPEN INDIRECT
	.BYTE	'_-'0		;OPEN INDEXED PC
	.BYTE	'<-'0		;RETURN TO INSTRUCTION
	.BYTE	'G-'0		;START PROGRAM
	.BYTE	'S-'0		;SINGLE INSTRUCTION
	.BYTE	ESC-'0		;SPECIAL NAME CHARACTER
	.BYTE	ALT1-'0		;SPECIAL NAME CHARACTER
	.BYTE	ALT2-'0		;SPECIAL NAME CHARACTER
	.BYTE	'E-'0		;ENABLE CYCLE STEAL + BG4-7
	.BYTE	'--'0		;SET NEGATIVE MODE
	.BYTE	' -'0		;SPACE -- IGNORE
	.BYTE	0		;ZERO BYTE ENDS THE TABLE
MSG1:	.BYTE	'?
	.BYTE	BELL
MSG2:	.BYTE	CR
	.BYTE	LF
	.BYTE	'=
	.BYTE	0
MSG3:	.BYTE	CR
	.BYTE	LF
	.BYTE	0
SPCCHR:	.BYTE	'S		;S IS THE NAME OF THE STATUS REGISTER
	.BYTE	'P		;P IS THE RUNNING PRIORITY
	.BYTE	0		;END OF THE LIST
	.EVEN
CMDTBL:	.WORD	OPNBYT		;\
	.WORD	OPNWD		;/
	.WORD	EOL		;<CR>
	.WORD	OPNEXT		;<LF>
	.WORD	OPNLNK		;L
	.WORD	OPNBR		;>
	.WORD	OPNIND		;@
	.WORD	OPNPCI		;_
	.WORD	OPNRET		;<
	.WORD	STRTHM		;G
	.WORD	ONCE		;S
	.WORD	SPECAL		;<ESC>
	.WORD	SPECAL		;<ALT1>
	.WORD	SPECAL		;<ALT2>
	.WORD	ENABLE		;E
	.WORD	MINUS		;-
	.WORD	SCAN00		;<SP>
;	THE FOLLOWING SHOULD HAVE ADDRESSES IN READ/WRITE
;	MEMORY AND ALLOW FOR ANY STACK SPACE USED BY ROUTINES WHO
;	MIGHT INTERRUPT AT WHAT EVER PRIORITY THE FUNCTIONS
;	ARE RUNNING AT

	.	=	12000

	.WORD	0		;STACK
	.WORD	0		;STACK
USRR0:	.WORD	0		;USER REGISTER 0
	.WORD	0		;USER REGISTER 1
	.WORD	0		;USER REGISTER 2
	.WORD	0		;USER REGISTER 3
	.WORD	0		;USER REGISTER 4
	.WORD	0		;USER REGISTER 5
USRSP:	.WORD	0		;USER STACK POINTER
USRPC:	.WORD	0		;USER PROGRAM COUNTER
USRST:	.WORD	0		;USER STATUS REGISTER
ODTPRI:	.WORD	0		;CONSOLE RUNNING PRIORITY
SINGLE:	.WORD	0		;THE SINGLE INSTRUCTION COUNT TO GO
ADDR:	.WORD	0		;THE CURRENT ADDRESS OF INTEREST
DOT:	.WORD	0		;THE PC FOR < COMMAND
STYLE:	.WORD	0		;THE LAST PREFORMED OPEN TYPE FLAG
USRKSR:	.BYTE	0		;THE SAVE BYTE FOR KBD STATUS REGISTER
USRTSR:	.BYTE	0		;THE SAVE BYTE FOR TTY STATUS REGISTER




;	.END	RESET		;START LIKE RESET BUTTON
	.	=	1000

;	SIMULATOR PROGRAM FOR KD11 CONSOLE FUNCTIONS

SIM00:	CLR	R1		;START WITH ALL SWITCHES OFF
SIM01:	MOV	@#177570,R0	;GET THE SWITCHES NOW
	BIT	#1,R1		;SEE IF BIT #0 WAS ON LAST LOOP
	BNE	SIM02		;BRANCH IF ALREADY SERVICED
	BIT	#1,R0		;SEE IF IT'S ON NOW
	BEQ	SIM02		;BRANCH IF NOTHING TO DO
	JMP	RESET		;JUMP TO THE ODT RESET ADDRESS

SIM02:	BIT	#2,R1		;SEE IF BIT #1 WAS ON LAST TIME 
	BNE	SIM03		;BRANCH IF ONLY UPDATING LEFT TO DO
	BIT	#2,R0		;SEE IF ON NOW
	BEQ	SIM03		;BRANCH IF NOT TIME TO STOP
	IOT			;USE IOT TRAP LIKE STOP ENTRY
SIM03:	MOV	R0,R1		;UPDATE THE LAST SEEN WORD
	BR	SIM01		;AND LOOP AGAIN


	.	=	4	;SET UP THE TRAP VECTORS

	.REPT	7
	.WORD	STOP		;STOP ENTRY TO ODT
	.WORD	PR7		;AT PR7 TO BOOT

	.ENDR

	.=50		;FOR THE FUNNY CONSOLE
	.WORD	STOP		;ENTRY POINT
	.WORD	PR7		;AND THE PRIORITY

	.=24		;RESET ON FUNNY CONSOLE PIS PWRF
	.WORD	RESET

	.END	SIM00		;START SIMULATOR
   